home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’93 / Digital Signature Forger / Source / DigitalSignature.h < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-03  |  15.5 KB  |  387 lines  |  [TEXT/MPS ]

  1. /************************************************************
  2.  
  3. Created: Monday, January 11, 1993 at 7:23PM
  4.  DigitalSignature.h
  5.  C Interface to the Macintosh Libraries
  6.  
  7.     ••• Apple Confidential •••
  8.     ••• Provided with AOCE Beta seed under license agreement with   •••
  9.     ••• Apple Computer, Inc.  Use for any purpose other than        •••
  10.     ••• development of AOCE-based Macintosh products is a violation •••
  11.     ••• of the license agreement.                                   •••
  12.  
  13.   Copyright Apple Computer, Inc. 1990-1993
  14.   All rights reserved
  15.  
  16. ************************************************************/
  17.  
  18.  
  19. #ifndef __DIGITALSIGNATURE__
  20. #define __DIGITALSIGNATURE__
  21.  
  22. #ifndef __FILES__
  23. #include <Files.h>
  24. #endif
  25.  
  26. #ifndef __MEMORY__
  27. #include <Memory.h>
  28. #endif
  29.  
  30. #ifndef __TYPES__
  31. #include <Types.h>
  32. #endif
  33.  
  34.  
  35. /* —————————————————————————— MACROS AND TRAP SELECTORS —————————————————————————— */
  36. #ifndef __DigitalSignature
  37. #define __DigitalSignature(count,selector) = { 0x203C, count, selector, 0xAA5D}
  38. #endif
  39.  
  40. #define kSIGNewContext                    1900
  41. #define kSIGDisposeContext                1901
  42.  
  43. #define kSIGSignPrepare                    1902
  44. #define kSIGSign                        1903
  45.  
  46. #define kSIGVerifyPrepare                1904
  47. #define kSIGVerify                        1905
  48.  
  49. #define kSIGDigestPrepare                1906
  50. #define kSIGDigest                        1907
  51.  
  52. #define kSIGProcessData                    1908
  53.  
  54. #define kSIGShowSigner                    1909
  55. #define kSIGGetSignerInfo                1910
  56. #define kSIGGetCertInfo                    1911
  57. #define kSIGGetCertNameAttributes        1912
  58. #define kSIGGetCertIssuerNameAttributes    1913
  59.  
  60. #define kSIGFileIsSigned                2500
  61. #define kSIGSignFile                    2501
  62. #define kSIGVerifyFile                    2502
  63.  
  64.  
  65. /* values of SIGNameAttributeType */
  66. enum {
  67.     kSIGCountryCode,
  68.     kSIGOrganization,
  69.     kSIGStreetAddress,
  70.     kSIGState,
  71.     kSIGLocality,
  72.     kSIGCommonName,
  73.     kSIGTitle,
  74.     kSIGOrganizationUnit,
  75.     kSIGPostalCode
  76. };
  77.  
  78. typedef unsigned short SIGNameAttributeType;
  79.  
  80. /* 
  81. Certificate status codes returned in SIGCertInfo or SIGSignerInfo from
  82. either SIGGetCertInfo or SIGGetSignerInfo respectively. kSIGValid means that
  83. the certificate is currently valid. kSIGPending means the certificate is
  84. currently not valid - but will be.  kSIGExpired means the certificate has
  85. expired. A time is always associated with a SIGCertStatus.  In each case the
  86. time has a specific interpretation.  When the status is kSIGValid the time is
  87. when the certificate will expire. When the status is kSIGPending the time is
  88. when the certificate will become valid. When the status is kSIGExpired the time
  89. is when the certificate expired. In the SIGCertInfo structure, the startDate
  90. and endDate fields hold the appropriate date information.  In the SIGSignerInfo
  91. structure, this information is provided in the certSetStatusTime field. In the
  92. SIGSignerInfo struct, the status time is actually represented by the SIGSignatureStatus
  93. field which can contain any of the types below. NOTE: The only time you will get 
  94. a kSIGInvalid status is when it pertains to a SIGSignatureStatus field and only when
  95. you get a signature that was created after the certificates expiration date, something
  96. we are not allowing on the Mac but that may not be restricted on other platforms. Also, 
  97. it will not be possible to get a kSIGPending value for SIGSignatureStatus on the Mac but
  98. possibly allowed by other platforms.
  99. */
  100.  
  101. /* Values for SIGCertStatus or SIGSignatureStatus */
  102. enum {
  103.     kSIGValid,        /* possible for either a SIGCertStatus or SIGSignatureStatus */
  104.     kSIGPending,    /* possible for either a SIGCertStatus or SIGSignatureStatus */
  105.     kSIGExpired,    /* possible for either a SIGCertStatus or SIGSignatureStatus */
  106.     kSIGInvalid        /* possible only for a SIGSignatureStatus */
  107. };
  108.  
  109. typedef unsigned short SIGCertStatus;
  110. typedef unsigned short SIGSignatureStatus;
  111.  
  112. /* Gestalt selector code - returns toolbox version in low-order word */
  113. #define gestaltDigitalSignatureVersion 'dsig'
  114.  
  115.  
  116. /* Number of bytes needed for a digest record when using SIGDigest */
  117. #define kSIGDigestSize 16
  118.  
  119. typedef Byte SIGDigestData[kSIGDigestSize], *SIGDigestDataPtr;
  120.  
  121. struct SIGCertInfo {
  122.     unsigned long    startDate;                /* cert start validity date */
  123.     unsigned long    endDate;                /* cert end validity date */
  124.     SIGCertStatus    certStatus;                /* see comment on SIGCertStatus for definition */
  125.     unsigned long    certAttributeCount;        /* number of name attributes in this cert */
  126.     unsigned long    issuerAttributeCount;    /* number of name attributes in this certs issuer */
  127.     Str255            serialNumber;            /* cert serial number */
  128. };
  129.  
  130. typedef struct SIGCertInfo SIGCertInfo;
  131. typedef SIGCertInfo *SIGCertInfoPtr;
  132.  
  133. struct SIGSignerInfo {
  134.     unsigned long        signingTime;        /* time of signing */
  135.     unsigned long        certCount;            /* number of certificates in the cert set */
  136.     unsigned long        certSetStatusTime;    /* Worst cert status time. See comment on SIGCertStatus for definition */
  137.     SIGSignatureStatus    signatureStatus;    /* The status of the signature. See comment on SIGCertStatus for definition*/
  138. };
  139.  
  140. typedef struct SIGSignerInfo SIGSignerInfo;
  141. typedef SIGSignerInfo *SIGSignerInfoPtr;
  142.  
  143. struct SIGNameAttributesInfo {
  144.     Boolean                 onNewLevel;
  145.     SIGNameAttributeType    attributeType;
  146.     ScriptCode                attributeScript;
  147.     Str255                    attribute;
  148. };
  149.  
  150. typedef struct SIGNameAttributesInfo SIGNameAttributesInfo;
  151. typedef SIGNameAttributesInfo *SIGNameAttributesInfoPtr;
  152.  
  153. typedef Ptr    SIGContextPtr;
  154. typedef Ptr SIGSignaturePtr;
  155.  
  156. /*
  157. Certificates are always in order. That is, the signers cert is always 0, the
  158. issuer of the signers cert is always 1 etc… to the number of certificates-1.
  159. You can use this constant for readability in your code.
  160. */
  161.  
  162. #define kSIGSignerCertIndex 0
  163.  
  164. /*
  165. Call back procedure supplied by developer, return false to cancel the current
  166. process.
  167. */
  168.  
  169. typedef pascal Boolean (*SIGStatusProcPtr)(void);
  170.  
  171. /*
  172. Resource id of standard signature icon suite, all sizes and colors are available.
  173. */
  174.  
  175. #define kSIGSignatureIconResID -5045
  176.  
  177. /* ——————————————————————————————— CONTEXT CALLS ——————————————————————————————— */
  178. /*
  179. To use the Digital Signature toolbox you will need a SIGContextPtr.  To create
  180. a SIGContextPtr you simply call SIGNewContext and it will create and initialize
  181. a context for you.  To free the memory occupied by the context and invalidate
  182. its internal data, call SIGDisposeContext. An initialized context has no notion
  183. of the type of operation it will be performing however, once you call
  184. SIGSignPrepare SIGVerifyPrepare, or SIGDigestPrepare, the contexts operation
  185. type is set and to switch  to another type of operation will require creating a
  186. new context. Be sure to pass the same context to corresponding toolbox calls
  187. (ie SIGSignPrepare, SIGProcessData, SIGSign)  in other words mixing lets say
  188. signing and verify calls with the same context is not allowed.
  189. */
  190.  
  191. #ifdef __cplusplus
  192. extern "C" {
  193. #endif
  194.  
  195. pascal OSErr SIGNewContext(SIGContextPtr *context)
  196.     __DigitalSignature(2, kSIGNewContext);
  197.  
  198. pascal OSErr SIGDisposeContext(SIGContextPtr context)
  199.     __DigitalSignature(2, kSIGDisposeContext);
  200.  
  201.  
  202. /* ——————————————————————————————— SIGNING CALLS ——————————————————————————————— */
  203. /*
  204. Once you have created a SIGContextPtr, you create a signature by calling
  205. SIGSignPrepare once, followed by n calls to SIGProcessData, followed by one call
  206. toRcpt SIGSign. To create another signature on different data but for the same
  207. signer, don't dispose of the context and call SIGProcessData for the new data
  208. followed by a call SIGSign again. In this case the signer will not be prompted
  209. for their signer and password again as it was already provided.  Once you call
  210. SIGDisposeContext, all signer information will be cleared out of the context and
  211. the signer will be re-prompted.  The signer file FSSpecPtr should be set to nil
  212. if you want the toolbox to use the last signer by default or prompt for a signer
  213. if none exists.  The prompt parameter can be used to pass a string to be displayed
  214. in the dialog that prompts the user for their password.  If the substring "^1"
  215. (without the quotes) is in the prompt string, then the toolbox will replace it
  216. with the name of the signer from the signer selected by the user.  If an empty
  217. string is passed, the following default string will be sent to the toolbox
  218. "\pSigning as ^1.".  You can call any of the utility routines after SIGSignPrepare
  219. or SIGSign to get information about the signer or certs.
  220. */
  221.  
  222. pascal OSErr SIGSignPrepare(SIGContextPtr context, const FSSpec *signerFile,
  223.     ConstStr255Param prompt, Size *signatureSize)
  224.     __DigitalSignature(8, kSIGSignPrepare);
  225.  
  226. pascal OSErr SIGSign(SIGContextPtr context, SIGSignaturePtr signature,
  227.     SIGStatusProcPtr statusProc)
  228.     __DigitalSignature(6, kSIGSign);
  229.  
  230.  
  231. /* ——————————————————————————————— VERIFYING CALLS ——————————————————————————————— */
  232. /*
  233. Once you have created a SIGContextPtr, you verify a signature by calling
  234. SIGVerifyPrepare  once, followed by n calls to SIGProcessData, followed by one
  235. call to SIGVerify. Check the return code from SIGVerify to see if the signature
  236. verified or not (noErr is returned on  success otherwise the appropriate error
  237. code).  Upon successfull verification, you can call any of the utility routines
  238. toRcpt find out who signed the data.
  239. */
  240.  
  241. pascal OSErr SIGVerifyPrepare(SIGContextPtr context, SIGSignaturePtr signature,
  242.     Size signatureSize, SIGStatusProcPtr statusProc)
  243.     __DigitalSignature(8, kSIGVerifyPrepare);
  244.  
  245. pascal OSErr SIGVerify(SIGContextPtr context)
  246.     __DigitalSignature(2, kSIGVerify);
  247.  
  248. /* —————————————————————————————— DIGESTING CALLS —————————————————————————————— */
  249. /*
  250. Once you have created a SIGContextPtr, you create a digest by calling
  251. SIGDigestPrepare once, followed by n calls to SIGProcessData, followed by one
  252. call to SIGDigest.  You can dispose of the context after SIGDigest as the
  253. SIGDigestData does not reference back into it.  SIGDigest returns the digest in
  254. digest.
  255. */
  256.  
  257. pascal OSErr SIGDigestPrepare(SIGContextPtr context)
  258.     __DigitalSignature(2, kSIGDigestPrepare);
  259.  
  260. pascal OSErr SIGDigest(SIGContextPtr context, SIGDigestData digest)
  261.     __DigitalSignature(4, kSIGDigest);
  262.  
  263.  
  264. /* —————————————————————————————— PROCESSING DATA —————————————————————————————— */
  265. /*
  266. To process data during a digest, sign, or verify operation call SIGProcessData
  267. as many times as necessary and with any sized blocks of data.  The data needs to
  268. be processed in the same order during corresponding sign and verify operations
  269. but does not need to be processed in the same sized chunks (i.e., the toolbox
  270. just sees it as a continuous bit stream).
  271. */
  272.  
  273. pascal OSErr SIGProcessData(SIGContextPtr context, const void *data, Size dataSize)
  274.     __DigitalSignature(6, kSIGProcessData);
  275.  
  276.  
  277. /* ——————————————————————————————— UTILITY CALLS ——————————————————————————————— */
  278. /*
  279. Given a context that has successfully performed a verification SIGShowSigner
  280. will  display a modal dialog with the entire distinguished name of the person
  281. who signed the data. the prompt (if supplied) will appear at the top of the
  282. dialog.  If no prompt is specified, the default prompt "\pVerification
  283. Successfull." will appear.
  284.  
  285. Given a context that has been populated by calling SIGSignPrepare, SIGSign or a
  286. successful SIGVerify, you can make the remaining utility calls:
  287.  
  288. SIGGetSignerInfo will return the SignerInfo record.  The certCount can be used
  289. toRcpt index into the certificate set when calling SIGGetCertInfo,
  290. SIGGetCertNameAttributes or SIGGetCertIssuerNameAttributes. The signingTime is
  291. only defined if the call is made after SIGSign  or SIGVerify. The certSetStatus
  292. will tell you the best status of the entire certificate set while
  293. certSetStatusTime will correspond to the time associated with that status (see
  294. definitions above).
  295.  
  296. SIGGetCertInfo will return the SIGCertInfo record when given a valid index into
  297. the cert set in  certIndex.  Note: The cert at index kSIGSignerCertIndex is
  298. always the signers certificate.  The  serial number, start date and end date
  299. are there should you wish to display that info.  The  certAttributeCount and
  300. issuerAttributeCount provide the number of parts in the name of that certificate
  301. or that certificates issuer respectively.  You use these numbers to index into
  302. either SIGGetCertNameAttributes or SIGGetCertIssuerNameAttributes to retrieve
  303. the name. The certStatus will tell you the status of the certificate while
  304. certStatusTime will correspond to the time associated with that status (see
  305. definitions above).
  306.  
  307. SIGGetCertNameAttributes and SIGGetCertIssuerNameAttributes return name parts
  308. of the certificate at  certIndex and attributeIndex.  The newLevel return value
  309. tells you wether the name attribute returned is at the same level in the name
  310. hierarchy as the previous attribute.  The type return value tells you  the type
  311. of attribute returned. nameAttribute is the actual string containing the name
  312. attribute.   So, if you wanted to display the entire distinguished name of the
  313. person who's signature was just validated you could do something like this;
  314.  
  315.     (…… variable declarations and verification code would preceed this sample ……)
  316.  
  317.     error = SIGGetCertInfo(verifyContext, kSIGSignerCertIndex, &certInfo);
  318.     HandleErr(error);
  319.  
  320.     for (i = 0; i <= certInfo.certAttributeCount-1; i++)
  321.         {
  322.         error = SIGGetCertNameAttributes(
  323.             verifyContext, kSIGSignerCertIndex, i, &newLevel, &type, theAttribute);
  324.         HandleErr(error);
  325.         DisplayNamePart(theAttribute, type, newLevel);
  326.         }
  327. */
  328.  
  329. pascal OSErr SIGShowSigner(SIGContextPtr context, ConstStr255Param prompt)
  330.     __DigitalSignature(4, kSIGShowSigner);
  331.  
  332. pascal OSErr SIGGetSignerInfo(SIGContextPtr context, SIGSignerInfo *signerInfo)
  333.     __DigitalSignature(4, kSIGGetSignerInfo);
  334.  
  335. pascal OSErr SIGGetCertInfo(SIGContextPtr context, unsigned long certIndex, SIGCertInfo *certInfo)
  336.     __DigitalSignature(6, kSIGGetCertInfo);
  337.  
  338. pascal OSErr SIGGetCertNameAttributes(SIGContextPtr context, unsigned long certIndex, 
  339.                                       unsigned long attributeIndex, SIGNameAttributesInfo *attributeInfo)
  340.     __DigitalSignature(8, kSIGGetCertNameAttributes);
  341.  
  342. pascal OSErr SIGGetCertIssuerNameAttributes(SIGContextPtr context, unsigned long certIndex, 
  343.                                             unsigned long attributeIndex, SIGNameAttributesInfo *attributeInfo)
  344.     __DigitalSignature(8, kSIGGetCertIssuerNameAttributes);
  345.  
  346.  
  347.  
  348. /* ——————————————————————————— FILE SIGN & VERIFY CALLS —————————————————————————— */
  349. /* 
  350. These calls allow you to detect the presence of a standard signtaure in a file as 
  351. well as sign and verify files in a standard way.  An example of this is the Finder, 
  352. which uses these calls to allow the user to "drop sign" a file.
  353.  
  354. To detect if a file is signed in the standard way, pass the FSSpec of the file to SIGFileIsSigned.
  355. A result of noErr means the file is in fact signed, otherwise, a kSIGNoSignature error will
  356. be returned.
  357.  
  358. Once you have created a SIGContextPtr, you can make calls to either sign or verify a file in
  359. a standard way: 
  360.  
  361. To sign a file, call SIGSignPrepare followed by 'n' number of calls to SIGSignFile,
  362. passing it the file spec for each file you wish to sign in turn.  You supply the context, the signature 
  363. size that was returned from SIGSignPrepare and an optional call back proc.  The call will take care of all
  364. the processing of data and affixing the signature to the file. If a signature already exists in the file, 
  365. it is replaced with the newly created signature.
  366.  
  367. To verify a file that was signed using SIGSignFile, call SIGVerifyFile passing it a new context and 
  368. the file spec.  Once this call has completed, if the verification is successfull, you can pass the context 
  369. to SIGShowSigner to display the name of the person who signed the file.
  370. */
  371.  
  372. pascal OSErr SIGFileIsSigned(const FSSpec *fileSpec) 
  373.     __DigitalSignature(2, kSIGFileIsSigned);
  374.  
  375. pascal OSErr SIGSignFile(SIGContextPtr context, Size signatureSize, const FSSpec *fileSpec, SIGStatusProcPtr statusProc) 
  376.     __DigitalSignature(8, kSIGSignFile);
  377.  
  378. pascal OSErr SIGVerifyFile(SIGContextPtr context, const FSSpec *fileSpec, SIGStatusProcPtr statusProc)
  379.     __DigitalSignature(6, kSIGVerifyFile);
  380.  
  381. #ifdef __cplusplus
  382. }
  383. #endif
  384.  
  385.  
  386. #endif
  387.